import struct
import time
import socket
import threading
import ctypes
import random
import numpy as np
import ipaddress

# 测试配置文件
import config
import crc8
import ipv4_header_gen



class HighSpeedFrameTransmitter:
    def __init__(self, interface, dest_mac, src_mac,
                 total_frames, interval_us, max_data_size,eth_type):
        self.interface = interface
        self.dest_mac = self.mac_str_to_bytes(dest_mac)
        self.src_mac = self.mac_str_to_bytes(src_mac)
        self.total_frames = total_frames
        self.interval_us = interval_us
        self.max_data_size = max_data_size      
        
        # 生成IPv4头
        self.ipv4_header = ipv4_header_gen.build_ipv4_header(
            src_ip=config.SRC_IPv4,
            dst_ip=config.DEST_IPv4,
            payload_len=config.TEST_DATA_SIZE,
            protocol=config.PROTOCOL_IPv4,
            identification=config.IDENTIFICATION_IPv4,
            ttl=config.TTL_IPv4,
        ) 
        
        # 配置常量
        self.ETH_P_ALL = 0x0003
        self.ETH_P_CUSTOM = eth_type                   
        
        # 创建原始socket
        self.sock = None
        self._create_socket()
        
        # 构建固定帧头
        self.frame_header = (
            self.dest_mac + 
            self.src_mac + 
            struct.pack(">H", self.ETH_P_CUSTOM)
        )
        # 序号标识
        self.sequence_num = 0
        
        # 生成crc查找表
        self.CRC8_TABLE_07 = crc8.make_crc8_table(poly=0x07)  
        

        
    class HighPrecisionTimer:
        def __init__(self, interval_us):
            self.interval_ns = interval_us * 1000
            self.next_time = time.perf_counter_ns()
        
        def wait_next(self):
            target = self.next_time
            self.next_time += self.interval_ns
            while time.perf_counter_ns() < target:
                pass
            return time.perf_counter_ns()
    
    def mac_str_to_bytes(self,mac_str):
        return bytes(int(x, 16) for x in mac_str.split(":"))
    
    def _create_socket(self):
        try:
            self.sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(self.ETH_P_ALL))
            #绕过路由表
            self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_DONTROUTE, 1)
            self.sock.bind((self.interface, 0))
        except PermissionError:
            print("ERROR: Permission denied. Run with sudo!")
            exit(1)
    
    def _generate_random_frame(self):
        """生成随机长度的帧，包含2字节序列号"""
        # 随机生成数据部分长度（不包括帧头、CRC和序列号）
        min_data_size = config.TEST_MIN_DATA_SIZE -config.CRC_LEN - config.SEQ_NUM_LEN  # 最小mac帧长
        max_data_size = self.max_data_size - config.CRC_LEN - config.SEQ_NUM_LEN  # 减去CRC和序列号
        
        if config.DO_RAND_SIZE == True:
            data_size = random.randint(min_data_size, max_data_size)
        else:
            data_size = max_data_size
        
        # 生成固定数据
        static_data = bytes([i%255 for i in range(data_size)])
        
        # 添加2字节序列号（大端序）
        sequence_bytes = struct.pack(">I", self.sequence_num)
        self.sequence_num = (self.sequence_num + 1) % (2**32)  # 序列号循环0-(2**32)
        
        # 构建帧数据（不包括CRC）
        frame_data = self.frame_header +self.ipv4_header + sequence_bytes + static_data
        
        # 计算CRC
        crc = crc8.crc8(frame_data, self.CRC8_TABLE_07)
        
        # 完整的帧
        frame = frame_data + crc
        return frame, len(frame)
    
    def _inject_errors(self,frame):
        '''
        根据概率注入错误比特
        '''
        if random.random() < config.ERROR_PROBABILITY:
            num_error_bits = random.randint(*config.ERROR_BITS_RANGE)
            
            # 将 bytes 转换为可变字节数组
            mutable_frame = bytearray(frame)
            frame_len = len(mutable_frame)
            
            # 总比特数 减去 CRC8 的1个字节
            total_checkable_bytes = frame_len - 1
            total_checkable_bits = total_checkable_bytes * 8
            
            if total_checkable_bits <= 0:
                return frame # 帧太短，无法注入错误
            
            # 随机选择 num_error_bits 个不同的比特位置
            bit_positions = np.random.choice(total_checkable_bits, num_error_bits, replace=False)
            
            for bit_pos in bit_positions:
                byte_index = bit_pos // 8  # 确定字节索引
                bit_in_byte = bit_pos % 8  # 确定字节中的比特位置 (0-7)
                #注入错误
                mutable_frame[byte_index] ^= (1 << bit_in_byte)
            
            return bytes(mutable_frame)
        else:
            # 不注入错误
            return frame 
        
    
    def print_config(self):
        print(f"Starting high-speed MAC frame transmitter on {self.interface}")
        print(f"Destination MAC: {':'.join(f'{b:02x}' for b in self.dest_mac)}")
        print(f"Source MAC: {':'.join(f'{b:02x}' for b in self.src_mac)}")
        print(f"Total frames to send: {self.total_frames}")
        print(f"Interval: {self.interval_us} microseconds")
        print(f"max data size: {self.max_data_size} bytes")
    
    def run(self):
        self.print_config()
        start_time = time.perf_counter_ns()
        
        try:
            # 高精度定时器
            self.timer = self.HighPrecisionTimer(self.interval_us)
            
            for seq in range(self.total_frames):
                frame,_ = self._generate_random_frame()
                if config.LOOP_TEST:
                    frame = self._inject_errors(frame)
                # 定时器
                self.timer.wait_next()
                # 发送固定帧
                self.sock.send(frame)
                
                # 打印统计
                if seq % 1000 == 0:
                    elapsed_ns = time.perf_counter_ns() - start_time
                    elapsed_sec = elapsed_ns / 1e9
                    rate = (seq + 1) / elapsed_sec if elapsed_sec > 0 else 0
                    print(f"Sent frame {seq+1}/{self.total_frames} | Rate: {rate:.2f} fps | Time: {elapsed_sec:.2f}s")
            
            print("\nAll frames sent successfully!")
        
        except KeyboardInterrupt:
            print("\nTransmission stopped by user")
        except Exception as e:
            print(f"\nERROR: {str(e)}")
            raise
        finally:
            self.sock.close()


    def run_with_callback(self, callback):
        """带GUI回调的发送方法"""
        self.print_config()
        start_time = time.perf_counter_ns()
        self.timer = self.HighPrecisionTimer(self.interval_us)
        seq = 0
        try:
            while seq < self.total_frames:
                frame, _ = self._generate_random_frame()
                if config.LOOP_TEST:
                    frame = self._inject_errors(frame)
                self.timer.wait_next()
                self.sock.send(frame)
                seq = seq + 1
                if seq % 100 == 0:  # 每100帧汇报一次状态
                    elapsed = (time.perf_counter_ns() - start_time) / 1e9
                    rate = seq / elapsed if elapsed > 0 else 0
                    callback({
                        "sent_frames": seq,
                        "rate": rate,
                        "elapsed_time": elapsed
                    })
                
        finally:
            self.sock.close()

# 使用示例
if __name__ == "__main__":
    # 配置参数
    # INTERFACE = "enp46s0"
    # DEST_MAC = b"\xf8\xe4\x3b\x32\x13\x93"
    # SRC_MAC = b"\xfc\x5c\xee\xa5\x4d\x7e"
    # TOTAL_FRAMES = 500
    # INTERVAL_US = 500       #单位：微秒
    # TEST_DATA_SIZE = 152-4-8-14-4  # 测试大于256的数据
    
    # 创建并运行发送器
    transmitter = HighSpeedFrameTransmitter(
        interface=config.INTERFACE1,
        dest_mac=config.INTERFACE2_MAC,
        src_mac=config.INTERFACE1_MAC,
        total_frames=config.TEST_TOTAL_FRAMES,
        interval_us=config.INTERVAL_US,
        max_data_size=config.TEST_DATA_SIZE,
        eth_type= config.ETHERTYPE
    )
    
    transmitter.run()